// Treasure-Maps Copyright 2009, Thea Ganoe. This program is distributed under the terms of the GNU General Public License


     //<![CDATA[
	//CDATA just means don't parse as XML

	var speed = 0;  // incremented by timers
	//these lats and lons center the USA at a zoom level 4:
	//which is where the front map should start for the USA
	var olongitude = -96.0;
	var olatitude = 37.0;
	var index = 0;
	var t; //used for the timer 
	var t2, t3, t4; //used for the timer
        var map;  //used by google
	var noheading = ''; //used for no heading pointer to show
        var routeLen = 0; //the global length counter
	var mileconvert = 0.000621;
	var speed = 3000;



var helpContent = "<br/><br/><a href='#' class='ulinedark' onclick='hideHelp()'>  Close Help </a>  <br/><br/>   This site displays custom maps by combining Google maps, GPX files and Picasa web albums for you to <i> visualize </i> and explore trails in their surrounding environment.  <br/><br/> Scroll down the list of routes on the left side of the screen. Press a Play button to run an animation that simultaneously shows the map location and picture. A map of the route will be drawn. <br/><br/> <img src='/static/buttonPlay.jpg'> <br/><br/>Or, just press the map button to create a static Google map and the html code to draw it on your own web page. <br/><br/> To look up a particular region, or type of trail, use the filter buttons to select your criteria and then press the Submit button. <br/><br/>  <img src='/static/filtershot.jpg'><br/><br/>  During the animation, control buttons can stop and back up. <br/><br/> <img src='/static/viewerShow2.jpg'><br/><br/>The Google Map is live, and can be zoomed and recentered as desired.  <br/><br/> Click an image to display the higher resolution original. <br/> <br/> Slow internet connection?  After the map and images finish loading, just press the stop button, then the restart button to run smoothly.<br/><br/> <img src='/static/viewerShow.jpg'><br/><br/> Distances are approximate.  <br/> <br/>   <a href='#' class='ulinedark' onclick='hideHelp()'>  Close Help </a>";

var aboutContent = " <br/><br/><a href='#' class='ulinedark' onclick='hideHelp()'>  Close About </a> <br/><br/>Treasure-Maps is an application that uses the Google Cloud architecture to host, process and serve your mapping applications.  <br/><br/> Anyone can create an account and publish an application that can use up to 500MB of storage and 5 million page views a month..free!  For more information about this service, visit <a href='http://code.google.com/appengine'> http://code.google.com/appengine </a><br/><br/>The Treasure-Maps website combines two web services, the Google Maps API and Picasa Web Albums to create a map and slideshow.  It operates on a simple 'connect-the-dots' concept, drawing lines between the GPS positions of the photographs.<br/> A prerecorded GPX file can also be displayed. <br/>The built-in editor allows any user with a valid Google account to create their own routes and save them.  It uses rich internet AJAX to create a comfortable experience for the user.  Features such as clicking on the map to set the latitude and longitude saves time and increases accuracy.  If the original photographs were geocoded by the device, that information can be used and completely automate the process!<br/><br/><br/>Please feel free to create your own routes! After you create them, you can link from your own website.  This website does not store photographs, it only saves the link it gets from the Picasa feed. <br/><br/> To access the editor, you must first press the 'Sign in' button.<br/><br/> To download this application visit <a href='http://code.google.com/p/treasure-maps/wiki/FirstReleaseAnnouncement'>the Google Code Home </a>   <a href='#' class='ulinedark' onclick='hideHelp()'>  Close About </a>";


function createXMLHttpRequest() {
      try{ return new ActiveXObject("Msxml2.XMLHTTP.6.0") }catch(e){}
      try{ return new ActiveXObject("Msxml2.XMLHTTP.3.0") }catch(e){}

      try{ return new ActiveXObject("Msxml2.XMLHTTP") }catch(e){}

      try{ return new ActiveXObject("Microsoft.XMLHTTP") }catch(e){}
      try{ return new XMLHttpRequest(); } catch(e) {}

      throw new Error("Could not find an XMLHttpRequest alternative.")
	return null;
}

function previousPt(lat, lon, lzoom) {
	//global variables
	var latitude = lat;
	var longitude = lon;
	var lzoom;
}

function currentPic(slide) {
	//global variables
	var slide = slide;
}

function GPXdata() {
	//global variables
	var GPXexists = false;
	var GPXdisplayed = false;
}

function loadPhoto(photoURL, getPic, longitude, latitude, heading, description) {
	//zoom has to go before panTo so the endpoint will be inside the clipping area
	// have to format the floating numbers from the distance measurements and convert to miles from meters
	// updates olongitude and olatitude at the end

			if ( isNaN(parseInt(longitude))) {
				longitude = previousPt.longitude;
			}
			if ( isNaN(parseInt(latitude))) {
				latitude = previousPt.latitude;
			}
	var gicon = 'giconN.png';
        var segLen = 0;
	var printtot = 0;
	map.panTo(new GLatLng(latitude, longitude));
	if ( olatitude != latitude ) {
	 	var polyline = new GPolyline([
  		  	new GLatLng( previousPt.latitude, previousPt.longitude),
  		  	new GLatLng(latitude, longitude)
			], "#ff0000", 5);
		segLen = polyline.getLength() ;
		//alert("segLen is " + segLen);
		if ( GPXdata.GPXexists == false ) { map.addOverlay(polyline) };
		//map.addOverlay(polyline);
		routeLen = routeLen + segLen;
		printtot = routeLen * mileconvert;
		segLen = segLen * mileconvert;
	}
	// figure out the heading of the camera for the picture to adjust the custom icon
	// headings are compass degrees and can only be 0, 45, 90, 125, 180, 225, 270, and 315.  Default is unknown case
	// NOTE:  does not display a marker if there is no picture
	if ( (photoURL != "") || (description != "" ) ) { 

		var degrees = parseInt(heading);

		switch (degrees)
		{
		case (degrees = 0):
			gicon = "giconN.png";
		break;
		case (degrees = 45):
 			 gicon = "giconNE.png";
		break;
		case (degrees = 90):
			 gicon = "giconE.png";
		break;
		case (degrees = 135):
			 gicon = "giconSE.png";
		break;
		case (degrees = 180):
			 gicon = "giconS.png";
		break;
		case (degrees = 225):
			 gicon = "giconSW.png";
		break;
		case (degrees = 270):
			 gicon = "giconW.png";
		break;
		case (degrees = 315):
			gicon = "giconNW.png";
		break;

		default:
  			gicon = "";
		
		} 

		document.getElementById("photo").src = photoURL + "?imgmax=512";
        	document.getElementById("getImg").href = getPic;

		var marker = new GMarker(new GPoint(longitude, latitude));
  		map.addOverlay(marker);
		index = index + 1;
		gmarkers[index] = marker ;
	 
		if ( index > 1)  {
			if (gicon != "") 
				marker.setImage("/static/icons/"+gicon);
	 			map.removeOverlay(gmarkers[index-1]);
		}
		document.getElementById("descriptionBox").innerHTML = description;
		if ( GPXdata.GPXexists == false ) {
		  document.getElementById("mileageBox").innerHTML =  " TOTAL: "+ printtot.toFixed(2) + " miles";
                }
	} else {
		//only displaying a segment without a picture
		//document.getElementById("mileageBox").innerHTML = "Length of Segment: "+ segLen.toFixed(2) + " miles";
	}
	previousPt.longitude = longitude;
	previousPt.latitude = latitude;

} // end load photo()


function nextPic() {
    // the next button was pressed
	if (currentPic.slide <  myObj.way.length - 1 ) {
		advancePic(currentPic.slide);
	} else
	{
		document.getElementById("stopBut").style.visibility = "hidden";
		document.getElementById("nextBut").style.visibility = "hidden";
		document.getElementById("restartBut").style.visibility = "visible"; 
		document.getElementById("backBut").style.visibility = "visible"; 
	}
}

function backPic(){
//changes the pictures and info, updates currentpic value
	do {
			
			document.getElementById("nextBut").style.visibility = "visible";
			currentPic.slide = currentPic.slide - 1;
			var i = currentPic.slide;
			
			if ( i < 1 ) {
				document.getElementById("backBut").style.visibility = "hidden";
			}
			img = myObj.way[i].img;
			getPic = myObj.way[i].getPic;
       			longitude = myObj.way[i].longitude;
        		latitude = myObj.way[i].latitude;
			heading = myObj.way[i].heading;
			//zoom = parseInt(myObj.way[i].zoom);
        		description = myObj.way[i].description;
        		loadPhoto(img, getPic, longitude, latitude, heading, description);
			routeLen = 0;
			
	}while ( img == "" || img == 'None' ) 
	//TAKES CARE OF THE CASE where bends in the route require a point plotted without pause and no picture, 
}	 
 
function delayPic() {

}

function advancePic(curpic){
//changes the pictures and info, updates currentpic value

	//do {
			var i = curpic  + 1;
			img = myObj.way[i].img;
			getPic = myObj.way[i].getPic;
       			longitude = myObj.way[i].longitude;
        		latitude = myObj.way[i].latitude;
			heading = myObj.way[i].heading;
        		var description = myObj.way[i].description;
		      	loadPhoto(img, getPic, longitude, latitude, heading, description);
			currentPic.slide = i;
			return i;
	//}while ( img == "" || img == 'None' ) 
	//TAKES CARE OF THE CASE where bends in the route require a point plotted without pause and no picture, 
}


function slideShow(curpic) {
	document.getElementById("stopBut").style.visibility = "visible";
	document.getElementById("nextBut").style.visibility = "hidden";
	document.getElementById("playBut").style.visibility = "hidden";
	document.getElementById("backBut").style.visibility = "hidden";

	if (curpic == -1 ) {
		curpic = currentPic.slide ;
	}

	if (document.images) {
		if (curpic <  myObj.way.length - 1 )
		{
			
 			var newpic = advancePic(curpic);  //moves the route and shows the pictures
			newint = parseInt(newpic);
			//this will give it a nice little delay when a new picture has just loaded;
			if ( myObj.way[curpic].img != "" ) { 
				t4 = setTimeout("slideShow(newint)", speed);
			} else t4 = setTimeout("slideShow(newint)", 1000);	

    		}
                else
		{
			document.getElementById("stopBut").style.visibility = "hidden";
			document.getElementById("nextBut").style.visibility = "hidden";
			document.getElementById("restartBut").style.visibility = "visible"; 
			document.getElementById("backBut").style.visibility = "visible"; 
	 	}

	} //end if document.images

} // end slideshow

function stopShow() {
	document.getElementById("stopBut").style.visibility = "hidden";
	document.getElementById("nextBut").style.visibility = "visible";
	document.getElementById("backBut").style.visibility = "visible";
	document.getElementById("playBut").style.visibility = "visible";
	document.getElementById("restartBut").style.visibility = "visible"; 
	clearTimeout(t); clearTimeout(t2); clearTimeout(t3); clearTimeout(t4);
}

function restartShow() {

	
	clearTimeout(t); clearTimeout(t2); clearTimeout(t3); clearTimeout(t4);
	document.getElementById("stopBut").style.visibility = "visible";
	document.getElementById("nextBut").style.visibility = "hidden";
	document.getElementById("backBut").style.visibility = "hidden";
	document.getElementById("playBut").style.visibility = "hidden";
	document.getElementById("restartBut").style.visibility = "hidden"; 
	currentpic = 0;
	map.clearOverlays();
        setParking();
	setRestrooms();
	var i= 0;
        var img = myObj.way[i].img;
        var getPic = myObj.way[i].getPic;
        var longitude = myObj.way[i].longitude;
        var latitude = myObj.way[i].latitude;
	var heading = myObj.way[i].heading;
        var description = myObj.way[i].description;
	olongitude = longitude;
	olatitude = latitude;
	//show the first picture & MAP
        loadPhoto(img, getPic, longitude, latitude, heading, description);
	routeLen = 0;
	map.clearOverlays();
        //alert("GPXexists is : " + GPXexists);
	//draw a gpx map if there is one:
	if ( GPXdata.GPXexists == true ) {

		var encodedPolyline = new GPolyline.fromEncoded({
    			color: "#FF0000",
    			weight: 3,
    			points: myGPX.encoded_points,
    			levels: myGPX.encoded_levels,
    			zoomFactor: 32,
    			numLevels: 4
		});
		map.addOverlay(encodedPolyline);
		//alert("printed gpx on map");
	}
	currentPic.slide = 0;
	setTimeout("slideShow(0)", 3000);
}

function setParking() {
	for (i = 0; i< parkingArray.length; i++) {
		plat = parkingArray[i].latitude;
		plon = parkingArray[i].longitude;
		var marker = new GMarker(new GPoint(plon, plat));
		map.addOverlay(marker);
		marker.setImage("/static/icons/giconP.png");
	}
}

function setRestrooms() {
	for (i = 0; i< restroomsArray.length; i++) {
		plat = restroomsArray[i].latitude;
		plon = restroomsArray[i].longitude;
		var marker = new GMarker(new GPoint(plon, plat));
		map.addOverlay(marker);
		marker.setImage("/static/icons/giconR.png");
	}
}

function postComment() {
	document.getElementById('btnComment').style.visibility = "hidden";
}

function dirtyComment() {
   	//user has entered the comment box so make the post button visible
	stopShow();
	//alert("in dirty");
 	document.getElementById('btnComment').style.visibility = "visible";
}

function runIt(zlevel){
	//use parseInt(zlevel) to create a valid integer for the zoom function to work correctly!
	var golatitude;
	var golongitude;

	var img = myObj.way[0].img;
	var getPic = myObj.way[1].getPic;
       	var description = myObj.way[0].description;
	document.getElementById("photo").src = img + "?imgmax=512";
        document.getElementById("getImg").href = getPic;
	document.getElementById("descriptionBox").innerHTML = description;
	map.clearOverlays();

	//map.panTo(new GLatLng(golatitude, golongitude));
	//alert("setting zoom in runIt" + zlevel);
	var newZoom = parseInt(zlevel);
	map.setZoom(newZoom);
	//draw a gpx map if there is one:
	if ( GPXdata.GPXexists == true ) {

		var encodedPolyline = new GPolyline.fromEncoded({
    			color: "#FF0000",
    			weight: 3,
    			points: myGPX.encoded_points,
    			levels: myGPX.encoded_levels,
    			zoomFactor: 32,
    			numLevels: 4
		});
		map.addOverlay(encodedPolyline);
	}
	currentPic.slide = 0;
	setTimeout("slideShow(0)", 3000);
}

function loadGPX(lzoom) { 
	//THIS FUNCTION  is part 2 of loadIt()
	//loading dynamic object myGPX into memory.  
	
	var gstring = document.getElementById('GPXbox').value;
	if  ( gstring.length > 2 ) {
		myGPX = JSON.parse(gstring);
	        GPXdata.GPXexists = true;
	}
	runIt(lzoom);
}

function loadIt(lzoom) {
        //this function is invoked by the frontpage callback function playView
	//the template aviewer.html has been served
	//loading dynamic object myObj into memory.  wait for it to load before continuing
	myObj = JSON.parse(document.getElementById('JSONbox').value)  ; 
	myObj.onLoad=loadGPX(lzoom);
}

function newLoad(lati, longi, zoomi) {
	//called to start setup from a direct link
        //initialize variables
	//window.scrollTo(60,10);
	var zoom = parseInt(zoomi);
        // var longitude =  document.forms[2].elements[1].value;
        // var latitude = document.forms[2].elements[0].value;
      	// Create the map and place it.
	map = new GMap2(document.getElementById("map"));
        map.setCenter(new GLatLng(lati, longi), zoom);
	previousPt.longitude = longi;
	previousPt.latitude = lati;
	GPXdata.GPXexists=false;
	GPXdata.GPXdisplayed = false;
  	map.setUIToDefault(); 
	map.enableContinuousZoom(); 
	map.setMapType(G_HYBRID_MAP);
	//map.setMapType(G_SATELLITE_TYPE);
	var mapControl = new GMapTypeControl();
	map.addControl(mapControl);
	map.addControl(new GLargeMapControl3D());
        map.addControl(new GScaleControl());
	loadGPX(zoom);
	// runIt draws the gpx lines
	//t3 = setTimeout("slideShow();", 6000);	
	   
    } //END newLOAD


function playView(routeKey, lats, lons, lzoom) {
	//called by: <button type="button" id="btnPlay" name="btnPlay" class="nav" onclick="playView('{{ route.key }}'lat,lon)" > play </button>
	// req.open url is mapped to the views.py function def aplay(request, route_key):
	//zoomIn(latlng?:GLatLng, doCenter?:Boolean, doContinuousZoom?:Boolean)
	//set global zoom:
	playing = true;
	// erase static map if drawn:
	closeMap();
	map.setCenter(new GLatLng(lats, lons), lzoom);
	//this will set the initial starting pt, it is an object with class members to be used like static vars
	previousPt.longitude = lons;
	previousPt.latitude = lats;
	GPXdata.GPXexists=false;
	GPXdata.GPXdisplayed = false;
	//map.setZoom(lzoom);
	//map.zoomIn();
	var req = createXMLHttpRequest();
 	req.open('GET', '/rpcRoute/'+ routeKey +"/play", true);
        req.onreadystatechange = onAddSuccess;
        req.send(null);

    // aplay returns respond(request, user, 'aviewer', {'ways':newStr, 'comments':comments_obj, 'leftLinks':linkList_obj, 'route':route})
    //at this point the server response is contained in aviewer.html
    function onAddSuccess(response) {
	//replaces the #_nodes with the slideshow
	//zooms one level
	//map.zoomIn(new GLatLng( lats, lons),true, true);
     	if (req.readyState != 4) {return; }
	//alert("in playView, zoom is "+ lzoom);
      	var serverResponse = req.responseText;
	var lastNode = document.getElementById("introWrap")
	lastNode.innerHTML = '';
	showNode = document.getElementById("leftImages");
	//document.getElementById(showNode).scrollTop=0;
	showNode.scrollTop = 0;
	showNode.innerHTML = serverResponse;
	loadIt(lzoom);
    }
}

function startUP() {
        //called by  intro.html on load
	var i= 0;
	var zoom = 4;
	var longitude = olongitude;
	var latitude = olatitude;
        // var longitude =  document.forms[2].elements[1].value;
        // var latitude = document.forms[2].elements[0].value;
      	// Create the map and place it.
	map = new GMap2(document.getElementById("map"));
        map.setCenter(new GLatLng(latitude, longitude), zoom);
  	map.setUIToDefault(); 
	map.enableContinuousZoom(); 
	map.setMapType(G_HYBRID_MAP);
	//map.setMapType(G_SATELLITE_TYPE);
	var mapControl = new GMapTypeControl();
	map.addControl(mapControl);
	map.addControl(new GLargeMapControl3D());
        map.addControl(new GScaleControl());
}

function addComment(routeKey) {
        getstr  =  document.getElementById("tbxComment").value ;
	//alert('getstr is ' + getstr);
	var body = "route_key=" + routeKey + "&cmtbx=" + getstr;
	//alert('body is ' + body);
	//use a POST requires pass it a body
	var req = createXMLHttpRequest();
 	req.open('POST', '/rpcComment/'+ routeKey +"/newComment", true);
        req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	req.setRequestHeader("Content-length", body.length);
	req.setRequestHeader("Connection", "close");
        req.onreadystatechange = onAddSuccess;
        req.send(body);

    //at this point the server response updates the comment list div
    function onAddSuccess(response) {
	
     	if (req.readyState != 4) {return; }
      	var serverResponse = req.responseText;
	var lastNode = document.getElementById("commentPlace");
	lastNode.innerHTML = '';
	lastNode.innerHTML = serverResponse;
	
	document.getElementById('btnComment').style.visibility = "hidden";
    }
}

function mapView(routeKey, lati, longi) {
	//called by: <button type="button" id="btnMap" 
	//need the path returned to draw the polygons on the map.
	closeMap();
	mapNode = document.getElementById("map");
	mapNode.style.visibility = 'hidden';
	var req = createXMLHttpRequest();
 	req.open('GET', '/rpcRoute/'+ routeKey +"/mapShow", true);
        req.onreadystatechange = onAddSuccess;
        req.send(null);

    function onAddSuccess(response) {
	//replaces the #_nodes with the slideshow
	//zooms one level
	//map.zoomIn(new GLatLng( lats, lons),true, true);
     	if (req.readyState != 4) {return; }
      	var serverResponse = req.responseText;
	var mg = document.createElement('div');
	mg.setAttribute('id', 'staticMap' );
	mg.innerHTML = serverResponse;
	pn = document.getElementById("platt");
	pn.insertBefore(mg, pn.firstChild);
    }
}

function closeMap() {
	//this function erases a static map if it were drawn
	//calling this function makes sure both types of maps aren't visible at same time
	var mg = document.getElementById("staticMap");
	//x.parentNode.removeChild(x); 
	if (mg) { mg.parentNode.removeChild( mg ); }
	mapNode = document.getElementById("map");
	mapNode.style.visibility = 'visible';
}

function searchRoutes() {
	//the submit button on the searchbox form triggers this function
	//this will do an ajax post to the server and filter the routes according to the user selection
	//url is action="rpcRouteSearch/"

	var states = document.getElementById('states')[document.getElementById('states').selectedIndex].innerHTML;
	var types = document.getElementById('types')[document.getElementById('types').selectedIndex].innerHTML;
	var orcas = document.getElementById('orcas')[document.getElementById('orcas').selectedIndex].innerHTML;
 	var locas =document.getElementById('locas')[document.getElementById('locas').selectedIndex].innerHTML;
	var body ="states=" + states + "&types=" + types + "&orcas=" + orcas + "&locas=" + locas;
	//alert(body);
	var req = createXMLHttpRequest();
 	req.open('POST', '/rpcRouteSearch/', true);
	req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	req.setRequestHeader("Content-length", body.length);
	req.setRequestHeader("Connection", "close");
        req.onreadystatechange = onAddSuccess;
        req.send(body);

    // aplay returns respond(request, user, 'aviewer', {'ways':newStr, 'comments':comments_obj, 'leftLinks':linkList_obj, 'route':route})
    //at this point the server response is contained in introRoutes.html
  function onAddSuccess(response) {
	//alert("in searchRoutes callback: " + req.readyState);
	//replaces the #_nodes with the slideshow
     	if (req.readyState != 4) {return; }
      	var serverResponse = req.responseText;
	var mg = document.getElementById("leftImages");
	mg.innerHTML = serverResponse;
	globalNode = 0;
    }
}

function showHelp(content) {
	var lastNode = document.getElementById('helpNode')
	lastNode.innerHTML = content;
    }

function hideHelp() {
	var lastNode = document.getElementById('helpNode')
	lastNode.innerHTML = "";
    }

function showLink(rkey, rnum) {
	//rkey is the database key, rnum is the node number on the screen to know where to display the answer
	//this function needs to change with the URL
	lstring = 'http://treasure-maps.appspot.com/route/'+ rkey + '/play' ;
	alert( lstring);
}


function selectObj(post,glat,glong) {
       
 	//sets the global node selected and then highlights it's div tag
	if (playing == true ) { return; }
	if (globalNode == post ) { return; }
	globalNode = post;
	//this loop resets all divs back to starting color
	for ( i = 1; i <= numPosts; i++ ) {
		var ego = i + "_nodepad";
		document.getElementById(ego).style.backgroundColor = "#CCCC9F";
	}

	var ego = post + "_nodepad";
	document.getElementById(ego).style.backgroundColor = "white";
	var marker = new GMarker(new GPoint(glong,glat));
	map.clearOverlays();
	map.addOverlay(marker);
	map.panTo(new GLatLng(glat,glong)); 
	gmarkers[1] = marker ;
	
}

function unload() {
	map.Dispose();
	GUnload()
	globalNode = 0;
	saved = true;
	playing = false;
	numPosts = 0 ;
	myObj = none ; 
	myGPX = none;
	parkingArray = '';
	restroomsArray = '';
	//var head = document.getElementsByTagName('head').item(0);
  	//var js = document.getElementById(scriptName);
  	//js.parentNode.removeChild(js);
	//location.reload(true);
}


 //]]>

